[アップデート] CloudWatch Logs メトリクスフィルターでディメンションがサポートされました!
コンバンハ、千葉(幸)です。
CloudWatch Logs のメトリクスフィルターがディメンションをサポートしました!
メトリクスフィルターで設定しているフィールドの値を、ディメンションとしてメトリクスとともにパブリッシュできるようになりました。(こう書くと何がなんやらですね。)
何ができるようになったのか
イメージとしては以下です。
メトリクスフィルターにディメンションを設定できるようになり、メトリクスフィルターからパブリッシュされたメトリクスにディメンションを付与することができるようになりました。
特定の条件にマッチしたログが出力された際に、さらなる詳細情報を付与できるようになった、というイメージです。
これだけだと分かりづらいので各用語の補足をしていきます。
CloudWatch Logs メトリクスフィルターとは
CloudWatch Logs メトリクスフィルターをロググループに関連づけることで、指定したパターンに一致した場合にCloudWatch にメトリクスを発行(パブリッシュ)できます。
平たく言えばログ監視の仕組みに使用できます。「ERROR
という文字列が含まれるログがロググループ内に書き込まれたら検知したい」というケースの場合、以下のイメージで実現できます。
- 「
ERROR
という文字列が含まれる」というフィルターパターンを持つメトリクスフィルターを作成し、CloudWatch Logs ロググループに関連づける - メトリクスフィルターがパターンマッチした場合にパブリッシュするメトリクス(名前空間、メトリクス名)を設定しておく
- 当該メトリクスに対してCloudWatch アラームを設定する
単純な例で考えれば、「マッチしたら対象のメトリクスに 1 をパブリッシュする」とメトリクスフィルターを設定しておき、対象のメトリクスに「値が 0 より大きかったらアラート状態に遷移させる」というCloudWatch アラームを設定することになります。
一つのロググループに複数のメトリクスフィルターを設定することもできます。
メトリクスフィルターの詳細は以下を参照してください。
CloudWatch のディメンションとは
CloudWatch のディメンションとは、メトリクスの一意の識別子として機能するものです。
平たく言えば、「名前空間とメトリクス名だけだと区別できないものに追加の観点を加える」ものです。
例えば以下の画像を見てください。EC2 インスタンスを稼働させると自動的に取得されるメトリクスです。
ここではCPUUtilization
というメトリクス名に注目します。このメトリクスは大枠としてEC2
という名前空間に属しています。よって、例えば RDS インスタンスで同じメトリクス名のCPUUtilization
が取得されていたとしても、明確に区別できます。
しかし、「どの EC2 インスタンスの CPU 使用率か」を区別するためには名前空間とメトリクス名だけでは不足しています。ここでインスタンスを区別するためにInstanceId
という切り口が加われば充足します。そのように機能するのがディメンションです。
ディメンションは 1 メトリクスあたり最大 10 個まで割り当てることができます。詳細は以下を参照してください。
メトリクスフィルターでディメンションを使用するとは
今回のアップデートの内容に戻ると、「メトリクスフィルターからプッシュするメトリクスにディメンションを付与することができるようになった」というものです。
以下ドキュメントに記載されている例をベースに説明します。
例えば以下のフィルターパターンを持つメトリクスフィルターがあったとします。
[ip, server, username, timestamp, request, status_code, bytes > 1000]
これはスペース区切りのログに対してフィールドを指定する書き方です。以下のようなフォーマットのログが出力されるケースが想定されます。(ここではダブルクォーテーションの前に\
が含まれていますが、実際に出力されるログで含まれていると正常に解釈されません。)
127.0.0.1 Prod frank [10/Oct/2000:13:25:15 -0700] \"GET /index.html HTTP/1.0\" 404 1534
上記のログが出力された場合、各フィールドには以下の値が含まれます。
{ "$status_code": "404", "$request": "GET /products/index.html HTTP/1.0", "$bytes": "1534", "$timestamp": "10/Oct/2000:13:25:15 -0700", "$username": "frank", "$server": "Prod", "$ip": "127.0.0.1" }
フィルターパターンにマッチするログが出力された場合、指定したメトリクスに値がプッシュされます。ここでは「1000バイトを超える場合」という条件のみでフィルターされ、それ以上の詳細は区別されません。
ここでディメンションとして以下を設定したとします。
"Server" : $server
これにより、ディメンションServer
としてserver
フィールドの値が含まれた状態でメトリクスがパブリッシュされます。(ログフォーマット例におけるProd
部が該当します。)
この設定を加えることによって、例えばProd
サーバーへのアクセスとDev
サーバーへのアクセスは別メトリクスとして解釈されます。Stg
という値が途中で増えても、設定を変更することなく自動で収集してくれます。
ディメンションを用いない状態でこれを実現しようとすると、メトリクスフィルターとメトリクス名をパターンごと(Prod
,Dev
,Stg
,,,)に分割して設定する必要がありました。
そう考えるだいぶお手軽になりましたね。
メトリクスフィルターでディメンションを設定する場合の注意点
以下の注意点があります。
- メトリクスフィルターに設定できるディメンションは最大で3つ
- メトリクスフィルターの「デフォルト値」と併用はできない
- JSON ログイベントもしくはスペース区切りのログイベントでしか使えない
- カスタムメトリクスの料金の高騰に注意
三つ目と四つ目について補足します。
JSON ログイベントもしくはスペース区切りのログイベントでしか使えない
例えば以下のようなフィルターパターンを持つメトリクスフィルターではディメンションを指定できません。
”ERROR"
?"ERROR" ?"WARN"
"ERROR" -"Exiting"
ディメンションとして出力するのはフィールドの値であるため、それを指定していないフィルターパターンの場合は対応していない、ということです。
カスタムメトリクスの料金の高騰に注意
メトリクスフィルターによりパブリッシュされた値は、カスタムメトリクスとして扱われます。そしてカスタムメトリクスはその数により課金されます。
例えば東京リージョンであれば、最初の 10,000個のメトリクスは 1個あたり0.3 USD /月かかります。
冒頭で挙げた例のようにProd
,Dev
,Stg
とディメンションの値がパブリッシュされる場合、それらは 3 つの別物のカスタムメトリクスとして扱われます。
タイムスタンプやクライアントのIPアドレスなどカーディナリティが高い(種類の絶対数が多い)フィールドをディメンションにした場合、メトリクス数が膨れ上がることになるので注意が必要です。
偶発的な高額請求を避けるため、特定の時間内で特定のディメンションに 1000 の異なる値が発行された場合、Amazon によりメトリクスフィルターが無効化されることがあるとのことです。
やってみた
ドキュメントに記載の例を実装した上でサンプルでログレコードを出力し、メトリクスにどのように値が出力されているかを確認します。
メトリクスフィルターの作成
Test
という名称のロググループにメトリクスフィルターを設定していきます。全部で3ステップあります。
フィルターパターンとして以下を設定し、次に進みます。
[ip, server, username, timestamp, request, status_code, bytes > 1000]
以下を指定し、画面を下にスクロールします。
- フィルター名:
test-filter
- メトリクス名前空間:
test-log
- メトリクス名:
Over1000byte
- メトリクス値:
1
続いて以下の値を設定していきます。
- デフォルト値
- Unit(単位)
- ディメンション
「デフォルト値」は、「ログが出力されているがパターンにマッチしない」場合にメトリクスにパブリッシュされる値です。今回のようなケースであれば0
を指定するのがセオリーでしょう。
しかし、ディメンションと併用はできず、「デフォルト値」に値を入れるとディメンション部がグレーアウトされます。よって今回は空欄にします。
以下を指定し、次に進みます。
- Unit:
なし
- ディメンション
- ディメンション名:
Server
- ディメンション値:
$server
- ディメンション名:
ディメンション値はフィルターパターンの内訳からプルダウンが用意されているため、選択するだけです。
最後のステップで設定内容を確認し、作成を実行します。
以下の通り正常に作成されました。
ログの出力とメトリクスの確認
ロググループTest
内にログストリームTest-Stream
を作成し、サンプルのログを出力します。
ログストリームの詳細画面から「アクション」→「ログイベントの作成」を実行することでログ出力ができます。
今回は以下のログイベントを1行ずつ順に作成します。
127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534 127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534 127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534 127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999 127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999 127.0.0.1 Prod chiba [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999 127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534 127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534 127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 1534 127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999 127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999 127.0.0.1 Dev saitama [10/Oct/2000:13:25:15 -0700] "GET /index.html HTTP/1.0" 404 999 hogehoge hogehoge hogehoge
以下を3回ずつ実施するということです。
Server
がProd
でフィルターパターンにマッチ(1000バイトより大きい)するものServer
がProd
でフィルターパターンにマッチしないものServer
がDev
でフィルターパターンにマッチするものServer
がDev
でフィルターパターンにマッチしないもの- ログフォーマットに則っていないもの
結果から言うと、パターンにマッチするもののみメトリクスに値が出力されました。フォーマットに則っているがマッチしないもの、そもそもフォーマットに則っていないものの場合、「0
が出力されるでもなく値そのものが出力されない」という状態でした。
パブリッシュされたメトリクスはこのように確認できます。指定した通りの名前空間、ディメンション、メトリクス名となっています。
実行するタイミングをちょっと失敗したためProd
の方は時間が空いていますが、それぞれ合計 3 のメトリクスが出力されています。
メトリクスフィルターが一つであっても出力先のメトリクスを分割できたため、それぞれの環境ごとの傾向を確認したり、 Prod の方だけはCloudWatchアラームを設定しておく、といった柔軟な使い方ができそうです。
終わりに
CloudWatch Logs メトリクスフィルターがディメンションの発行に対応した、というアップデートでした。
今回の例ではディメンションは一つだけでしたが、最大三つまで設定できるため、より細かな集計も実現できます。カスタムメトリクスの料金には気をつけつつ、要件に応じて活用してみてください。
ディメンションを設定するとデフォルト値が設定できないため、「ログは出力されているがマッチしていない」場合はメトリクスの値が null になることも覚えておくといいでしょう。
以上、千葉(幸)がお送りしました。